home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-08-10 | 8.7 KB | 305 lines | [TEXT/CWIE] |
- // ===========================================================================
- // CSimpleTCPServer.cp ©1995-1998 Metrowerks Inc. All rights reserved.
- // ===========================================================================
- // Servers are endpoints that watch and wait for connection requests from
- // remote clients. The actual connection to and interaction with remote clients
- // is handled by the "responders."
-
- #include "CSimpleTCPServer.h"
-
- #include <UNetworkFactory.h>
- #include <LWindow.h>
- #include <LApplication.h>
- #include <UMemoryMgr.h>
-
- #include <Sound.h>
-
-
- // ===========================================================================
- // • Resource IDs
- // ===========================================================================
-
- const PP_PowerPlant::ResIDT PPob_WaitIngWindow = 131;
- const PP_PowerPlant::PaneIDT pPort = 'PORT';
- const PP_PowerPlant::PaneIDT pAddress = 'ADDR';
- const PP_PowerPlant::PaneIDT pMaxConnection = 'MCON';
- const PP_PowerPlant::PaneIDT pCurrConnection = 'CCON';
- const PP_PowerPlant::PaneIDT pRejectedConnection = 'RCON';
-
- // ---------------------------------------------------------------------------
- // • CSimpleTCPServer
- // ---------------------------------------------------------------------------
-
- CSimpleTCPServer::CSimpleTCPServer(
- LCommander* inSuper)
- : LSingleDoc(inSuper)
- {
- mWindow = nil;
- mEndpoint = nil;
- mServerThread = nil;
- mQuitWhenDone = false;
- mSaveOption = 0;
- }
-
- // ---------------------------------------------------------------------------
- // • ~CSimpleTCPServer
- // ---------------------------------------------------------------------------
-
- CSimpleTCPServer::~CSimpleTCPServer()
- {
- if (mEndpoint) {
- mEndpoint->RemoveListener(this);
- delete mEndpoint;
- mEndpoint = nil;
- }
-
- if (mServerThread)
- mServerThread->DeleteThread();
- }
-
- // ---------------------------------------------------------------------------
- // • ListenToMessage
- // ---------------------------------------------------------------------------
-
- void
- CSimpleTCPServer::ListenToMessage(
- PP_PowerPlant::MessageT inMessage,
- void * /* ioParam */)
- {
- switch (inMessage) {
- case T_LISTEN:
- if (mServerThread) {
- mServerThread->ResumeServerThread();
- }
- break;
- }
- }
-
- // ---------------------------------------------------------------------------
- // • WaitForConnections
- // ---------------------------------------------------------------------------
- // Wait for connection(s) from remote machine(s) using the parameters that have
- // been passed to us. The connection information window is also opened at this time.
- //
- // This routine creates an endpoint and a thread for the server process.
- // When the thread runs, it will bind the endpoint and wait for T_Listen events.
- // Responses to T_Listens will be handled on NEW endpoints. This endpoint ONLY listens.
-
- void
- CSimpleTCPServer::WaitForConnections(
- UInt32 inListenQueueSize,
- UInt32 inPort)
- {
- mConnectionCount = mRejectionCount = 0;
-
- CreateServerWindow(inListenQueueSize, inPort);
-
- mEndpoint = PP_PowerPlant::UNetworkFactory::CreateTCPEndpoint();
- mEndpoint->AddListener(this);
-
- mServerThread = new CTCPServerThread(
- inListenQueueSize,
- inPort,
- mEndpoint,
- this);
-
- mServerThread->Resume();
- }
-
-
- // ---------------------------------------------------------------------------
- // • IsIdle
- // ---------------------------------------------------------------------------
-
- Boolean
- CSimpleTCPServer::IsIdle()
- {
- if (mEndpoint == nil) {
- return true;
- }
-
- PP_PowerPlant::EEndpointState netState = mEndpoint->GetState();
- return ((netState == PP_PowerPlant::endpoint_Idle) || (netState == PP_PowerPlant::endpoint_Unbound));
- }
-
-
- // ---------------------------------------------------------------------------
- // • ServerThreadDied
- // ---------------------------------------------------------------------------
-
- void
- CSimpleTCPServer::ServerThreadDied()
- {
- mServerThread = nil;
-
- //Re-issue the quit command when we are ready.
- if (mQuitWhenDone) {
- PP_PowerPlant::LApplication* theApp = dynamic_cast<PP_PowerPlant::LApplication*>(GetSuperCommander());
- if ( theApp ) {
- theApp->DoQuit(mSaveOption);
- }
- }
-
- delete this;
- }
-
- // ---------------------------------------------------------------------------
- // • Disconnect
- // ---------------------------------------------------------------------------
-
- void
- CSimpleTCPServer::Disconnect()
- {
- if (mServerThread) {
- mServerThread->StartDisconnect();
- }
- }
-
- PP_PowerPlant::LTCPEndpoint*
- CSimpleTCPServer::GetEndPoint() const
- {
- return mEndpoint;
- }
-
- // ---------------------------------------------------------------------------
- // • CreateServerWindow
- // ---------------------------------------------------------------------------
-
- void
- CSimpleTCPServer::CreateServerWindow(
- UInt32 inListenQueueSize,
- UInt32 inPort)
- {
- PP_PowerPlant::LCaption* theField;
-
- mWindow = PP_PowerPlant::LWindow::CreateWindow(PPob_WaitIngWindow, this);
-
- theField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pPort));
- ThrowIfNil_ (theField);
- theField->SetValue(inPort);
-
- theField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pAddress));
- ThrowIfNil_ (theField);
-
- {
- PP_PowerPlant::StDeleter<PP_PowerPlant::LInternetMapper>
- theMapper( PP_PowerPlant::UNetworkFactory::CreateInternetMapper() );
-
- PP_PowerPlant::StDeleter<PP_PowerPlant::LInternetAddress>
- tempAddress( theMapper->GetLocalAddress() );
-
- Str255 tempDescriptor;
- theField->SetDescriptor(tempAddress->GetIPDescriptor(tempDescriptor));
- }
-
- theField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pMaxConnection));
- ThrowIfNil_ (theField);
- theField->SetValue(inListenQueueSize);
-
- mConnectionCountField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pCurrConnection));
- ThrowIfNil_ (mConnectionCountField);
- mConnectionCountField->SetValue(mConnectionCount);
-
- mRejectionCountField = dynamic_cast<PP_PowerPlant::LCaption*> (mWindow->FindPaneByID(pRejectedConnection));
- ThrowIfNil_ (mRejectionCountField);
- mRejectionCountField->SetValue(mRejectionCount);
- }
-
- // ---------------------------------------------------------------------------
- // • AddToConnectionCount
- // ---------------------------------------------------------------------------
- void
- CSimpleTCPServer::AddToConnectionCount(short theCount)
- {
- mConnectionCount += theCount;
- mConnectionCountField->SetValue(mConnectionCount);
-
- //Start disconnect if we are quitting and the connection count is 0
- if ((mConnectionCount == 0) && (mQuitWhenDone))
- Disconnect();
- }
-
- // ---------------------------------------------------------------------------
- // • IncRejectionCount
- // ---------------------------------------------------------------------------
- void
- CSimpleTCPServer::IncRejectionCount()
- {
- mRejectionCount++;
- mRejectionCountField->SetValue(mRejectionCount);
- }
-
- // ---------------------------------------------------------------------------
- // • BindCompleted
- // ---------------------------------------------------------------------------
- // We are now waiting for T_Listens... show the connection window
-
- void
- CSimpleTCPServer::BindCompleted()
- {
- mWindow->Show();
- }
-
- // ---------------------------------------------------------------------------
- // • BindFailed
- // ---------------------------------------------------------------------------
- // Could not bind to the requested port.
-
- void
- CSimpleTCPServer::BindFailed()
- {
- SignalPStr_("\pBind Failed");
- delete this;
- }
-
- // ---------------------------------------------------------------------------
- // • AllowSubRemoval
- // ---------------------------------------------------------------------------
- // If user tries to close the main window, and we have ongoing connections,
- // then block the action. If we don't have any connections then
- // interpret this as a request to close the server.
-
- Boolean
- CSimpleTCPServer::AllowSubRemoval(
- LCommander *inSub)
- {
- if ((inSub == mWindow) && (mConnectionCount > 0)) {
- SysBeep(30);
- return false;
- }
- else
- return LSingleDoc::AllowSubRemoval(inSub);
- }
-
- // ---------------------------------------------------------------------------
- // • AttemptQuitSelf
- // ---------------------------------------------------------------------------
- // Close our connection before quitting. We re-issue the quit command via
- // the ServerThreadDied method once we are done.
-
- Boolean
- CSimpleTCPServer::AttemptQuitSelf(
- SInt32 inSaveOption)
- {
- //This may seem odd, but...
- // subcommanders are called in order of creation so
- // this AttemptQuitSelf is called before any of the
- // responers it may have spawned.
- // Thus we return true here if mConnectionCount > 0
- // to give those a chance to get called too.
- if (mConnectionCount > 0)
- return true;
-
- if (mQuitWhenDone) {
- return LCommander::AttemptQuitSelf(inSaveOption);
- } else {
- mQuitWhenDone = true;
- mSaveOption = inSaveOption;
- if (mConnectionCount == 0) {
- Disconnect();
- }
- return false;
- }
- }
-
-